# cython: language_level=3
#!/usr/bin/python
# -- coding:utf8 --

import numpy as np
import pandas as pd
from datetime import datetime, timedelta, date
import re
import app.model_phl.util_log as utils
import json
import time


# 判断是否为手机号
def get_num_is_phone(x):
    """
    该函数判断一个字符串是否为手机号
    :param tel:
    :return:
    """
    x = str(x).replace(' ', '')
    if re.match(r"^[+63,63,0123456789]\d{10,13}$", str(x)):
        return 1
    else:
        return 0


def get_string_capital(name, cal_type='cnt'):
    if get_is_none(name):
        return -999977
    name_list = str(name).split(' ')
    name_cnt = len(name_list)
    name_str_cnt = len(str(name).strip())
    if cal_type == 'cnt':
        return name_cnt
    elif cal_type == 'namestrcnt':
        return name_str_cnt
    elif cal_type == 'strdistinctcnt':
        return len(set(str(name).replace(' ', '')))
    elif cal_type == 'firstworduppercnt':
        upper_cnt = 0
        for name in name_list:
            if get_is_none(name):
                continue
            if name[0].isupper():
                upper_cnt = upper_cnt + 1
        return upper_cnt
    elif cal_type == 'firstwordupperpct':
        upper_cnt = 0
        for name in name_list:
            if get_is_none(name):
                continue
            if name[0].isupper():
                upper_cnt = upper_cnt + 1
        return get_cal_division(upper_cnt, name_cnt)
    elif cal_type == 'worduppercnt':
        upper_cnt = 0
        for name in name_list:
            if get_is_none(name):
                continue
            for word in name:
                if word.isupper():
                    upper_cnt = upper_cnt + 1
        return upper_cnt
    elif cal_type == 'wordupperpct':
        upper_cnt = 0
        for name in name_list:
            if get_is_none(name):
                continue
            for word in name:
                if word.isupper():
                    upper_cnt = upper_cnt + 1
        return get_cal_division(upper_cnt, name_str_cnt)
    return -999976


# 获取与当前时间相差x的日期，秒
def get_timedelta_strtime(time_end, time_start):
    try:
        if get_is_none(time_end) or get_is_none(time_start):
            return -999977
        if len(str(time_end)) < 15 or len(str(time_start)) < 15:
            time_start = datetime.strptime(str(time_start)[0:10], "%Y-%m-%d")
            time_end = datetime.strptime(str(time_end)[0:10], "%Y-%m-%d")
        else:
            time_start = datetime.strptime(str(time_start)[0:19], "%Y-%m-%d %H:%M:%S")
            time_end = datetime.strptime(str(time_end)[0:19], "%Y-%m-%d %H:%M:%S")
        total_seconds = (time_end - time_start).total_seconds()
        if total_seconds < 0:
            return -999977
        return total_seconds
    except Exception as e:
        utils.get_logger().error(e)
        return -999976


# linux时间转成日期字符格式
def convert_ts_date(t):
    try:
        if get_is_none(t):
            return -999976
        if len(str(t)) > 10:
            t = int(t) / 1000
        timestr = datetime.fromtimestamp(int(t)).strftime("%Y-%m-%d %H:%M:%S")
        return timestr
    except Exception as e:
        utils.get_logger().error(t)
        utils.get_logger().error(e)
        return -999976


def convert_utc_ts_date(t):
    try:
        if get_is_none(t):
            return -999976
        if len(str(t)) > 10:
            t = int(t) / 1000
        timestr = datetime.utcfromtimestamp(int(t)).strftime("%Y-%m-%d %H:%M:%S")
        return timestr
    except Exception as e:
        utils.get_logger().error(t)
        utils.get_logger().error(e)
        return -999976


def get_interval_linuxtime(time_end, time_start):
    try:
        if get_is_none(time_end):
            return -2
        if get_is_none(time_start):
            return -1
        if time_end > 10000000000:
            time_end = time_end / 1000
        if time_start > 10000000000:
            time_start = time_start / 1000
        return int(time_end) - int(time_start)
    except Exception as e:
        utils.get_logger().error(e)
        return -999976


# 完全匹配
def get_is_match(parameter1, parameter2):
    try:
        if parameter1 == parameter2:
            return 1
        else:
            return 0
    except Exception as e:
        utils.get_logger().error(e)
        return -999976


# 判断参数是否为空
def get_is_none(x):
    if x is None or str(x).split('.')[0].replace(' ', '').lower().strip() in ['-999999', '-999976', '-999977',
                                                                              '-999978', '-999998',
                                                                              '-999999.0', '-999976.0', '-999977.0',
                                                                              '-999978.0',
                                                                              'none', 'nan', 'nat', '',
                                                                              '000000000000000']:
        return True
    else:
        return False


def get_is_null(x):
    if get_is_none(x):
        return 1
    else:
        return 0


# 字符处理
def get_str_format(x, is_del_blank=0):
    if get_is_none(x):
        return ''
    if is_del_blank == 0:
        return str(x).replace('"', '').strip().lower()
    else:
        return str(x).replace('"', '').replace(' ', '').strip().lower()


def get_format_username(*args):
    username = []
    for name in args:
        if get_is_none(name):
            name = ''
        else:
            name = str(name).replace('"', '').strip().lower()
            username.append(name)
    return ' '.join(username)


def name_birthday_list(first_name, middle, last_name, birthday):
    if get_is_none(birthday):
        return None
    return [get_format_username(first_name, middle, last_name, str(birthday + timedelta(days=1))),
            get_format_username(first_name, middle, last_name, str(birthday)),
            get_format_username(first_name, middle, last_name, str(birthday + timedelta(days=-1)))]


def get_mobile_phone_format(phone, country='PHL'):
    if phone is None or str(phone) == '-999999':
        return ''
    phone = str(phone).split(',')[0]
    if get_is_none(phone):
        return ''
    if country == 'PHL':
        phone = re.sub('\D', '', str(phone))
        phone = re.sub('^63', '', str(phone))
        phone = re.sub('^0', '', str(phone))
    return phone


def get_concat_list(*agrs):
    re_list = []
    for v in agrs:
        if v != '':
            re_list.append(v)
    return re_list


def get_value_is_inlist(match_name, match_list):
    try:
        if get_is_none(match_name) or get_is_none(match_list):
            return -999977
        if match_name in match_list:
            return 1
        else:
            return 0
    except Exception as e:
        utils.get_logger().error(e)
        return -999976


# 编辑距离
def get_edit_distance(str1, str2):
    # 动态规划求编辑距离
    # param s1: 字符串1
    # param s2: 字符串2

    len1 = len(str1)
    len2 = len(str2)
    # 初始化矩阵
    matrix = [[i + j for j in range(len2 + 1)] for i in range(len1 + 1)]
    for row in range(len1):
        for col in range(len2):
            comp = [matrix[row + 1][col] + 1, matrix[row][col + 1] + 1]
            if str1[row] == str2[col]:
                comp.append(matrix[row][col])
            else:
                comp.append(matrix[row][col] + 1)
                # 对相邻字符交换位置的处理判断
            if row > 0 and col > 0:
                if str1[row] == str2[col - 1] and str1[row - 1] == str2[col]:
                    comp.append(matrix[row - 1][col - 1] + 1)
            matrix[row + 1][col + 1] = min(comp)

    return matrix[len1][len2]


# 姓名相似度
def get_name_similarity(name1, name2):
    if get_is_none(name1) or get_is_none(name2):
        return -999977
    # 有部分用户姓名有短线，将短线换成空格
    name1 = re.sub(r'[^A-Za-z0-9\s]+', '', str(name1))
    name2 = re.sub(r'[^A-Za-z0-9\s]+', '', str(name2))
    # 姓名按照空格拆分成数组，并对这个数组排序，排序的目的是为了之后方便匹配
    name1_list = (str(name1).lower().split(' '))
    name2_list = (str(name2).lower().split(' '))
    name1_list_format = []
    name2_list_format = []
    for name in name1_list:
        if get_is_none(name) == False:
            name1_list_format.append(str(name).strip())
    for name in name2_list:
        if get_is_none(name) == False:
            name2_list_format.append(str(name).strip())
    name1_str = ''.join(name1_list_format)
    name2_str = ''.join(name2_list_format)
    if name1_str in name2_str and len(name1_str) >= 10:
        return 1
    if name2_str in name1_str and len(name2_str) >= 10:
        return 1
    # 拆分之后找到短的姓名
    if len(name1_list_format) <= len(name2_list_format):
        name_short_list = name1_list_format
        name_long_list = name2_list_format
    else:
        name_short_list = name2_list_format
        name_long_list = name1_list_format
    # 姓名拆分出来后，如果两个集合属于包含关系，则匹配，否则开始算编辑距离
    if set(name_short_list) <= set(name_long_list) and len(name_short_list) > 1:
        return 1
    else:
        # 循环比较两个字符串，求每个姓名最小编辑距离和/较短的姓名的长度和
        min_edit_distance_sum = 0
        name_len_sum = 0
        for nameshort1 in name_short_list:
            min_edit_distance = -1
            for namelong2 in name_long_list:
                morelongname = namelong2
                if len(morelongname) < len(nameshort1):
                    morelongname = nameshort1
                edit_distance = get_edit_distance(nameshort1, namelong2)
                if min_edit_distance == -1:
                    min_edit_distance = edit_distance
                    namelen = morelongname
                else:
                    if edit_distance < min_edit_distance:
                        min_edit_distance = edit_distance
                        namelen = morelongname
            min_edit_distance_sum += min_edit_distance
            name_len_sum += len(namelen)
        return 1 - round(min_edit_distance_sum / name_len_sum, 2)


def get_cal_division(numerator, denominator):
    try:
        if denominator == 0:
            return -999978
        elif get_is_none(numerator) or get_is_none(denominator):
            return -999977
        else:
            return round(numerator / denominator, 2)
    except Exception as e:
        utils.get_logger().error(e)
        return -999976


# 是否满足条件
def get_is_match_condition(x, value):
    try:
        x = float(x)
        if x >= value:
            return True
        else:
            return False
    except:
        return True


# 找到满足时间窗口的数据
def get_windows_time_df(df, cal_time_field, windows_type, windows_value):
    if df.empty:
        return df
    df_tmp = df[df[cal_time_field] >= 0].copy().reset_index()
    # 找到满足时间窗口的数据
    if windows_value == 'all':
        return df_tmp
    else:
        if windows_type == 'days':
            return df_tmp[df_tmp[cal_time_field] <= 3600 * 24 * windows_value]
        elif windows_type == 'hours':
            return df_tmp[df_tmp[cal_time_field] <= 3600 * windows_value]
        elif windows_type == 'minutes':
            return df_tmp[df_tmp[cal_time_field] <= 60 * windows_value]


def get_digital_value(value):
    try:
        if get_is_none(value):
            return -999977
        else:
            return round(float(value), 2)
    except:
        return -999976


def get_int_value(value):
    try:
        if get_is_none(value):
            return -999977
        else:
            return int(value)
    except:
        return -999976


def get_extra_device_json(x, key_list, value_type='str'):
    if value_type == 'str':
        default_value = ''
        error_value = '-999976'
    else:
        default_value = -999998.0
        error_value = -999976.0
    try:
        try:
            value = json.loads(x)
        except:
            value = x
        for key in key_list:
            value = value.get(key, default_value)
        if value_type == 'str':
            return (value)
        elif value_type == 'unixtime':
            if len(str(value)) < 11:
                value = time.mktime(time.strptime(value, "%Y-%m-%d"))
            else:
                value = time.mktime(time.strptime(value, "%Y-%m-%d HH:mm:ss"))
            return int(value)
        elif value_type == 'bool':
            if str(value).strip().lower() == 'true':
                value = 1
            if str(value).strip().lower() == 'false':
                value = 0
            else:
                value = -1
            return get_digital_value(value)
        elif value_type == 'int':
            return int(value)
        else:
            return get_digital_value(value)
    except Exception as e:
        return error_value


# 判断规则集rules是否都在rule_list里面
def get_rule_all_in_list(rules, rule_list):
    is_all_in = 1
    for rule in rules.keys():
        if rule not in rule_list:
            is_all_in = 0
    return is_all_in
